package org.pms.web.jsf.controller;

import java.util.Date;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;

import org.apache.log4j.Logger;
import org.pms.core.entity.Experience;
import org.pms.core.entity.Person;
import org.pms.core.exception.ServiceException;
import org.pms.core.service.PersonService;
import org.pms.core.service.PersonServiceImpl;
import org.pms.web.jsf.util.JsfUtil;

/**
 * Controller que trabalha com o detalhe de dados de uma pessoa
 * 
 * Ações definidas: 
 *   * detailSetup   : Obtem detalhe da pessoa e redireciona para tela consulta 
 *   * editSetup     : Obtem detalhe da pessoa e redireciona para tela edição
 *   * newSetup      : Inicializa dados nova pessoa e redireciona para tela edição
 *   * edit          : Operação que Salva dados alterados
 *   * newExperience : Adiciona no cadastro experiência em branco (não salva experiencia no banco)
 *   * getPerson     : Obter objeto pessoa para alteração de dados 
 * 
 * @author Paulo
 * 
 */
@ManagedBean
@SessionScoped
public class PersonDetailController {
	private static Logger logger = Logger.getLogger(PersonDetailController.class);
	private static final String GENERIC_ERROR = "Ocorreu um erro genérico!";
	
	private Person person;
	
	private PersonService personService;
	
	/**
	 * Instancia ou inicializa dependência do controller
	 */
	public PersonDetailController() {
		personService = new PersonServiceImpl();
    }
	
	/**
	 * Valida data de nascimento
	 * @param context contexto faces
	 * @param toValidate 
	 * @param value data de nascimento digitada
	 */
	public void validateBirthDate(FacesContext context, UIComponent toValidate, Object value) {  
	    Date now = new Date();
	    Date birthDate = (Date) value;   
	  
	    if (birthDate.getTime() > now.getTime()) {
	        ((UIInput)toValidate).setValid(false);  
	  
	        JsfUtil.addErrorMessage(context, toValidate.getClientId(context), " *A data nascimento não pode ser futura ");
	    }  
	}
	
	/**
	 * Inicializa dados para visualização detalhe da pessoa (consulta de dados)
	 * @return String ação que envia para a tela de consulta detalhe pessoa
	 */
	public String detailSetup() {
		FacesContext context = FacesContext.getCurrentInstance();
		try {
			person = context.getApplication().evaluateExpressionGet(context,
					"#{item}", Person.class);
		} catch (Exception e) {
			logger.error(GENERIC_ERROR,e);
			JsfUtil.addErrorMessage(GENERIC_ERROR);
		}
		
		return "person_detail";
	}
	
	/**
	 * Inicializa dados para edição do detalhe da pessoa 
	 * @return String próxima ação do jsf
	 */
	public String editSetup() {
		FacesContext context = FacesContext.getCurrentInstance();
		
		try {		
			person = context.getApplication().evaluateExpressionGet(context,
					"#{item}", Person.class);
		} catch (Exception e) {
			logger.error(GENERIC_ERROR,e);
			JsfUtil.addErrorMessage(GENERIC_ERROR);
		}
		
		return "person_edit";
	}
	
	/**
	 * Inicializa dados para criar nova pessoa
	 * @return String ação que envia para tela edição detalhe
	 */
	public String newSetup() {
		person = new Person();
		person.setActive(true);
		
		return "person_edit";
	}
	
	/**
	 * Salva dados alterados
	 * @return String ação que envia para tela listagem de pessoas
	 */
	public String edit() {		
		
		try {
			personService.savePerson(person);
			JsfUtil.addSuccessMessage("Pessoa " + person.getName() + " salva com sucesso!");
		} catch (ServiceException se) {
			JsfUtil.addErrorMessage(se.getMessage());
		} catch (Exception e) {
			logger.error(GENERIC_ERROR,e);
			JsfUtil.addErrorMessage(GENERIC_ERROR);
		}
		
		return "person_list";
	}


	/**
	 * Adiciona nova experiencia à pessoa (sem salvar no banco)
	 * @return String ação que envia para a tela edição detalhe
	 */
	public String newExperience() {
		try {
			person.getPersonExperiences().add(new Experience());
		}  catch (Exception e) {
			logger.error(GENERIC_ERROR,e);
			JsfUtil.addErrorMessage(GENERIC_ERROR);
		}
		
		return "person_edit";
	}
	
	/**
	 * Exclui experiencia da pessoa (sem salvar no banco)
	 * @return String ação que envia para a tela edição detalhe
	 */
	public String deleteExperience() {
		FacesContext context = FacesContext.getCurrentInstance();
		try {
			Experience experience = context.getApplication().evaluateExpressionGet(context,
					"#{personExperience}", Experience.class);
			person.getPersonExperiences().remove(experience);
			
		}  catch (Exception e) {
			logger.error(GENERIC_ERROR,e);
			JsfUtil.addErrorMessage(GENERIC_ERROR);
		}
		
		return "person_edit";
	}
	
	/**
	 * Obtem pessoa a ser trabalha (edição de dados)
	 * @return Person pessoa a ser trabalhada 
	 */
	public Person getPerson() {
		return person;
	}
}
